<?php
/*
 * description：
 * author：wh
 * email：
 * createTime：{2020/4/3} {9:23} 
 */

namespace wanghua\general_utility_tools_php\file\upload;


use wanghua\general_utility_tools_php\oss\alicloud\Objects;
use GuzzleHttp\Client;
use GuzzleHttp\Psr7\MultipartStream;
use GuzzleHttp\Psr7\Utils;
use wanghua\general_utility_tools_php\huawei\obs\InitObs;
use wanghua\general_utility_tools_php\Mmodel;
use wanghua\general_utility_tools_php\oss\huawei\obs\Config;
use wanghua\general_utility_tools_php\tool\Tools;

/**
 * 上传组件
 * 支持单图，多图，单文件，多文件
 * Class FileUpload
 * @package libraries
 */
class FileUpload
{
    //文件扩展
    protected $file_ext = 'ico,jpg,jpeg,png,gif,pdf,zip,rar,xls,xlsx,doc,docx';
    //图片扩展
    protected $img_ext = 'ico,jpg,jpeg,png,gif';

    public $unique_key = '';//唯一key，临时文件会存储至该目录，推荐使用用户id

    public $file_lists_urls = [];//要读取的文件地址列表
    /**
     * 文件存放目录
     *
     * 注意：后面不要“/”
     * 注意：后面不要“/”
     * 注意：后面不要“/”
     * @var string
     */
    private $file_dir = '/uploads';

    /**
     * desc：默认目录/uploads
     *
     * eg：/uploads/user/head_image 或 /files_manage/goods/images
     *
     * 注意：后面不要“/”
     * 注意：后面不要“/”
     * 注意：后面不要“/”
     *
     * author：wh
     * @param $file_dir
     */
    function setFileDir($file_dir){
        $this->file_dir = $file_dir;
    }
    /**
     * desc：单图
     *
     * 【！！！必须确认php.ini中upload_max_filesize的配置足够大，否则上传失败但不会报错！！！】
     *
     * author：wh
     * @param string $file_upload_name 表单文件元素name值
     * @param int $size 大小,默认2M
     * @param string $ext 允许的扩展
     * @return array
     */
    function image($file_upload_name = 'file_upload', $size=10, $ext=''){
        if(!$this->uploadMaxFilesizeCheck($size)){
            return Tools::set_res(1, '上传文件受限');
        }
        // 获取表单上传文件 例如上传了001.jpg
        $file = request()->file($file_upload_name);
        if(empty($file)){
            return Tools::set_res(1, '请上传文件');
        }
        // 移动到框架应用根目录/uploads/ 目录下
        $outer_req_url = $this->file_dir.'/image';
        $physics_path = 'public'.$outer_req_url;
        $root_path = explode('vendor',__DIR__)[0];
        $upload_dir = $root_path.$physics_path;
        if(!is_dir($upload_dir)){
            mkdir($upload_dir, 0777, true);
        }
        if(empty($file)){
            return Tools::set_res(1, '上传文件不存在');
        }

        if(empty($ext)) $ext = $this->img_ext;

        $info = $file->validate(['size'=>$size * 1024 * 1024, 'ext'=>$ext])->move($upload_dir);
        if($info){
            //原文件名
            $source_file_name = $info->getInfo('name');

            //文件类型
            $file_type = $info->getInfo('type');

            // 输出扩展名 jpg
            $extension = $info->getExtension();

            // 输出 20160820/42a79759f284b767dfcb2a0197904287.jpg
            $save_name = $info->getSaveName();

            // 输出 42a79759f284b767dfcb2a0197904287.jpg
            $new_filename = $info->getFilename();

            $relative_url = $outer_req_url.'/'.str_replace('\\', '/', $save_name);
            $result = [
                'prefix'=>request()->domain().$outer_req_url,//访问前缀
                'source_file_name'=>$source_file_name,
                'file_type'=>$file_type,
                'extension'=>$extension,
                'save_name'=>str_replace('\\', '/', $save_name),
                'new_filename'=>$new_filename,
                'real_path'=>$this->dealPath($root_path.'public'.$relative_url),//物理路径
                'outer_req_url'=>request()->domain().$relative_url,
                'outer_req_relative_url'=>$relative_url,
                'size'=>$info->getSize(),
            ];
            return Tools::set_res(0, '上传成功', $result);
        }else{
            // 上传失败获取错误信息
            return Tools::set_res(1, $file->getError());
        }
    }

    /**
     * desc：多图
     *
     * 【！！！必须确认php.ini中upload_max_filesize的配置足够大，否则上传失败但不会报错！！！】
     *
     * author：wh
     * @param string $file_upload_name 表单文件元素name值
     * @param int $size 大小,默认2M
     * @param string $ext 允许的扩展
     * @return array
     */
    function images($file_upload_name = 'file_upload', $size=10, $ext=''){
        if(!$this->uploadMaxFilesizeCheck($size)){
            return Tools::set_res(1, '上传文件受限');
        }
        // 获取表单上传文件
        $files = request()->file($file_upload_name);
        if(empty($files)){
            return Tools::set_res(1, '请上传文件');
        }
        $outer_req_url = $this->file_dir.'/image';
        $physics_path = 'public'.$outer_req_url;
        $root_path = explode('vendor',__DIR__)[0];
        $upload_dir = $root_path.$physics_path;
        if(!is_dir($upload_dir)){
            mkdir($upload_dir, 0777, true);
        }

        if(empty($ext)) $ext = $this->img_ext;

        $result = [];
        $error = [];
        foreach($files as $file){
            if(!is_object($file)){
                return Tools::set_res(1, '请上传正确的文件');
            }
            // 移动到框架应用根目录/uploads/ 目录下
            $info = $file->validate(['size'=>$size * 1024 * 1024, 'ext'=>$ext])->move($upload_dir);
            if($info){
                //原文件名
                $source_file_name = $info->getInfo('name');

                //文件类型
                $file_type = $info->getInfo('type');

                // 输出扩展名 jpg
                $extension = $info->getExtension();

                // 输出 20160820/42a79759f284b767dfcb2a0197904287.jpg
                $save_name = $info->getSaveName();

                // 输出 42a79759f284b767dfcb2a0197904287.jpg
                $new_filename = $info->getFilename();

                $relative_url = $outer_req_url.'/'.str_replace('\\', '/', $save_name);
                $result[] = [
                    'prefix'=>request()->domain().$outer_req_url,//访问前缀
                    'source_file_name'=>$source_file_name,
                    'file_type'=>$file_type,
                    'extension'=>$extension,
                    'save_name'=>str_replace('\\', '/', $save_name),
                    'new_filename'=>$new_filename,
                    'real_path'=>$this->dealPath($root_path.'public'.$relative_url),//物理路径
                    'outer_req_url'=>request()->domain().$relative_url,
                    'outer_req_relative_url'=>$relative_url,
                    'size'=>$info->getSize(),
                ];
            }else{
                //忽略错误
                // 上传失败获取错误信息
                $error[] = $file->getError();
            }
        }

        $msg = '上传成功';
        $code = 0;
        if(count($error) > 0){
            $msg = '上传失败;提示：'.implode(',', $error);//顺带返回错误信息
            $code = 1;
        }
        return Tools::set_res($code, $msg, $result);
    }


    /**
     * desc：单文件
     *
     * 【！！！必须确认php.ini中upload_max_filesize的配置足够大，否则上传失败但不会报错！！！】
     *
     * author：wh
     * @param string $file_upload_name 表单文件元素name值
     * @param int $size 大小,默认10M
     * @param string $ext 允许的扩展
     * @return array
     */
    function file($file_upload_name = 'file_upload', $size=10, $ext=''){
        if(!$this->uploadMaxFilesizeCheck($size)){
            return Tools::set_res(1, '上传文件受限');
        }
        // 获取表单上传文件 例如上传了001.jpg
        $file = request()->file($file_upload_name);
        if(empty($file)){
            return Tools::set_res(1, '请上传文件');
        }
        // 移动到框架应用根目录/uploads/ 目录下
        $outer_req_url = $this->file_dir.'/file';
        $physics_path = 'public'.$outer_req_url;

        $root_path = explode('vendor',__DIR__)[0];

        $upload_dir = $root_path.$physics_path;
        if(!is_dir($upload_dir)){
            mkdir($upload_dir, 0777, true);
        }
        if(empty($file)){
            return Tools::set_res(1, '上传文件不存在');
        }

        if(empty($ext)) $ext = $this->file_ext;

        $info = $file->validate(['size'=>$size * 1024 * 1024, 'ext'=>$ext])->move($upload_dir);
        if($info){
            //原文件名
            $source_file_name = $info->getInfo('name');

            //文件类型
            $file_type = $info->getInfo('type');

            // 输出扩展名 jpg
            $extension = $info->getExtension();

            // 输出 20160820/42a79759f284b767dfcb2a0197904287.jpg
            $save_name = $info->getSaveName();

            // 输出 42a79759f284b767dfcb2a0197904287.jpg
            $new_filename = $info->getFilename();

            $relative_url = $outer_req_url.'/'.str_replace('\\', '/', $save_name);
            $result = [
                'prefix'=>request()->domain().$outer_req_url,//访问前缀
                'source_file_name'=>$source_file_name,
                'file_type'=>$file_type,
                'extension'=>$extension,
                'save_name'=>str_replace('\\', '/', $save_name),
                'new_filename'=>$new_filename,
                'real_path'=>$this->dealPath($root_path.'public'.$relative_url),//物理路径
                'outer_req_url'=>request()->domain().$relative_url,
                'outer_req_relative_url'=>$relative_url,
                'size'=>$info->getSize(),
            ];
            return Tools::set_res(0, '上传成功', $result);
        }else{
            // 上传失败获取错误信息
            return Tools::set_res(1, $file->getError());
        }
    }

    /**
     * desc：多文件
     *
     * 【！！！必须确认php.ini中upload_max_filesize的配置足够大，否则上传失败但不会报错！！！】
     *
     * author：wh
     * @param string $file_upload_name 表单文件元素name值
     * @param int $size 单文件大小,默认10M
     * @param string $ext 允许的扩展
     * @return array
     */
    function files($file_upload_name = 'file_upload', $size=10, $ext=''){
        if(!$this->uploadMaxFilesizeCheck($size)){
            return Tools::set_res(1, '上传文件受限');
        }

        $root_path = explode('vendor',__DIR__)[0];
        // 获取表单上传文件
        $files = request()->file($file_upload_name);
        if(empty($files)){
            return Tools::set_res(1, '请上传文件');
        }
        $outer_req_url = $this->file_dir.'/file';
        $physics_path = 'public'.$outer_req_url;
        $upload_dir = $root_path.$physics_path;
        if(!is_dir($upload_dir)){
            mkdir($upload_dir, 0777, true);
        }

        if(empty($ext)) $ext = $this->file_ext;

        $result = [];
        $error = [];
        foreach($files as $file){
            // 移动到框架应用根目录/uploads/ 目录下
            $info = $file->validate(['size'=>$size * 1024 * 1024, 'ext'=>$ext])->move($upload_dir);
            if($info){
                //原文件名
                $source_file_name = $info->getInfo('name');

                //文件类型
                $file_type = $info->getInfo('type');

                // 输出扩展名 jpg
                $extension = $info->getExtension();

                // 输出 20160820/42a79759f284b767dfcb2a0197904287.jpg
                $save_name = $info->getSaveName();

                // 输出 42a79759f284b767dfcb2a0197904287.jpg
                $new_filename = $info->getFilename();

                $relative_url = $outer_req_url.'/'.str_replace('\\', '/', $save_name);
                $result[] = [
                    'prefix'=>request()->domain().$outer_req_url,//访问前缀
                    'source_file_name'=>$source_file_name,
                    'file_type'=>$file_type,
                    'extension'=>$extension,
                    'save_name'=>str_replace('\\', '/', $save_name),
                    'new_filename'=>$new_filename,
                    'real_path'=>$this->dealPath($root_path.'public'.$relative_url),//物理路径
                    'outer_req_url'=>request()->domain().$relative_url,
                    'outer_req_relative_url'=>$relative_url,
                    'size'=>$info->getSize(),
                ];
            }else{
                //忽略错误
                // 上传失败获取错误信息
                $error[] = $file->getError();
            }
        }
        $msg = '上传成功';
        $code = 0;
        if(count($error) > 0){
            $msg = '上传失败;提示：'.implode(',', $error);//顺带返回错误信息
            $code = 1;
        }
        return Tools::set_res($code, $msg, $result);
    }


    /**
     * desc：单文件或多文件上传至阿里云OSS服务
     *
     * author：wh
     * @param array $config 配置
     *  //阿里云oss配置
    'aliyun_oss_config'           => [
    //项目应用名称
    'bucket'=>'wanlliuyinli-adm',//每创建一个bucket必须标明前缀，代表这个bucket属于哪个项目
    'UserPrincipalName'=>'wanghua@1113242774600735.onaliyun.com',
    'Password'=>'0osE4cGo%tllnP1|uOQADPhM}Y?obR4U',
    'AccessKeyId'=>'LTAI5tPqn1n7jugviVoGqFfa',
    'AccessKeySecret'=>'BRoB5TdcUAFEuIR11BbN3R47Cm4Yep',
    //https://help.aliyun.com/zh/oss/user-guide/regions-and-endpoints?spm=a2c4g.11186623.0.0.41ae2effA6oZar
    'region_id'=>'cn-chengdu',//这里配置不能包含oss-前缀，否则提示：Invalid signing region in Authorization header
    //西南1（成都）
    //oss-cn-chengdu
    //oss-cn-chengdu.aliyuncs.com
    //oss-cn-chengdu-internal.aliyuncs.com
    'endpoint'=>'oss-cn-chengdu.aliyuncs.com',//成都节点
    'sts_endpoint'=>'sts.cn-chengdu.aliyuncs.com',//sts服务节点
    ]
     * @param string $unique_id 唯一id，可以是用户id，可以是其它用于区分的标识，默认存放在（项目名称/控制器/方法/(唯一标识，可为空)/年月日/*.jpg）
     * @param string $file_upload_name 文件上传控件的name值，必须带[]，例如：file_upload[]
     * @param string $oss_type oss类型，可选值：ali_cloud 阿里云，hua_wei 华为云（待扩展）
     * @param int $size 单文件大小,默认10M
     * @param string $ext 允许的文件扩展名
     * @return array
     */
    function filesUploadToAliCloudOss($config,$unique_id='',$file_upload_name = 'file_upload',$size=10, $ext=''){
        return Mmodel::catch(function ()use ($config,$unique_id,$file_upload_name,$size,$ext){
            $ini_upload_max_filesize = str_replace('M','',ini_get('upload_max_filesize'));
            if(($size > $ini_upload_max_filesize)){
                return Tools::set_res(1, '上传文件size受限，不能超过upload_max_filesize='.ini_get('upload_max_filesize').'M');
            }
            // 获取表单上传文件
            $files = request()->file($file_upload_name);
            if(empty($files)){
                return Tools::set_res(1, '请上传文件');
            }
            //扩展
            if(empty($ext)) $ext = $this->file_ext;
            //初始化阿里云OSS客户端
            $oss_obj= new Objects($config);
            //默认存储地址
            $file_save_dir = $this->setFileSaveDir($unique_id);
            $urls = [];
            foreach($files as $file){
                if(!$file->isValid()){
                    return Tools::set_res(1,'文件不合法');
                }
                $check_size = $file->checkSize($size*1024*1024);
                if(!$check_size){
                    return Tools::set_res(1,'文件大小超限');
                }
                $check_res = $file->checkExt($ext);
                if(!$check_res){
                    return Tools::set_res(1,'请上传合法文件');
                }
                $extension = explode('.',$file->getInfo('name'))[1];
                $new_filename = 'file_'.Tools::rand_str(18).'.'.explode('.',$file->getInfo('name'))[1];
                //必须加后缀
                $filename = $file_save_dir.$new_filename;

                // 从文件流上传
                $res = $oss_obj->fileUpload($filename, $file->getInfo('tmp_name'));//上传之前的临时文件物理地址
                $urls[] = [
                    'prefix'=>explode('.com',$res['info']['url'])[0].'.com',//访问前缀
                    'source_file_name'=>$file->getInfo('name'),//源文件名
                    'size'=>$file->getInfo('size'),//大小(b)
                    'extension'=>$extension,//扩展名
                    'file_type'=>$file->getInfo('type'),//文件后缀
                    'save_name'=>$filename,//保存文件名
                    'new_filename'=>$new_filename,//新文件名
                    'real_path'=>$res['info']['url'],//实际路径
                    'outer_req_url'=>$res['info']['url'],//外部访问地址
                    'outer_req_relative_url'=>$res['info']['url'],//外部访问相对地址
                ];
            }
            return Tools::set_ok('ok', $urls);
        });
    }

    /**
     * desc：单文件上传至阿里云OSS
     *
     * author：wh
     * @param array $config 配置
     *  //阿里云oss配置
    'aliyun_oss_config'           => [
    //项目应用名称
    'bucket'=>'wanlliuyinli-adm',//每创建一个bucket必须标明前缀，代表这个bucket属于哪个项目
    'UserPrincipalName'=>'wanghua@1113242774600735.onaliyun.com',
    'Password'=>'0osE4cGo%tllnP1|uOQADPhM}Y?obR4U',
    'AccessKeyId'=>'LTAI5tPqn1n7jugviVoGqFfa',
    'AccessKeySecret'=>'BRoB5TdcUAFEuIR11BbN3R47Cm4Yep',
    //https://help.aliyun.com/zh/oss/user-guide/regions-and-endpoints?spm=a2c4g.11186623.0.0.41ae2effA6oZar
    'region_id'=>'cn-chengdu',//这里配置不能包含oss-前缀，否则提示：Invalid signing region in Authorization header
    //西南1（成都）
    //oss-cn-chengdu
    //oss-cn-chengdu.aliyuncs.com
    //oss-cn-chengdu-internal.aliyuncs.com
    'endpoint'=>'oss-cn-chengdu.aliyuncs.com',//成都节点
    'sts_endpoint'=>'sts.cn-chengdu.aliyuncs.com',//sts服务节点
    ]
     * @param string $unique_id 唯一id，可以是用户id，可以是其它用于区分的标识，默认存放在（项目名称/控制器/方法/(唯一标识，可为空)/年月日/*.jpg）
     * @param string $file_upload_name 文件上传控件的name值，例如：file_upload
     * @param string $oss_type oss类型，可选值：ali_cloud 阿里云，hua_wei 华为云（待扩展）
     * @param int $size 单文件大小,默认10M
     * @param string $ext 允许的文件扩展名
     * @return array
     */
    function fileUploadToAliCloudOss($config,$unique_id='',$file_upload_name = 'file_upload',$size=10, $ext=''){
        return Mmodel::catch(function ()use ($config,$unique_id,$file_upload_name,$size,$ext){
            $ini_upload_max_filesize = str_replace('M','',ini_get('upload_max_filesize'));
            if(($size > $ini_upload_max_filesize)){
                return Tools::set_res(1, '上传文件size受限，不能超过upload_max_filesize='.ini_get('upload_max_filesize').'M');
            }
            // 获取表单上传文件
            $file = request()->file($file_upload_name);
            if(empty($file)){
                return Tools::set_res(1, '请上传文件');
            }
            //扩展
            if(empty($ext)) $ext = $this->file_ext;
            //初始化阿里云OSS客户端
            $oss_obj= new Objects($config);
            //默认存储地址
            $file_save_dir = $this->setFileSaveDir($unique_id);
            $urls = [];
            if(!$file->isValid()){
                return Tools::set_res(1,'文件不合法');
            }
            $check_size = $file->checkSize($size*1024*1024);
            if(!$check_size){
                return Tools::set_res(1,'文件大小超限');
            }
            $check_res = $file->checkExt($ext);
            if(!$check_res){
                return Tools::set_res(1,'请上传合法文件');
            }
            $extension = explode('.',$file->getInfo('name'))[1];
            $new_filename = 'file_'.Tools::rand_str(18).'.'.explode('.',$file->getInfo('name'))[1];
            //必须加后缀
            $filename = $file_save_dir.$new_filename;

            // 从文件流上传
            $res = $oss_obj->fileUpload($filename, $file->getInfo('tmp_name'));//上传之前的临时文件物理地址
            $urls[] = [
                'prefix'=>explode('.com',$res['info']['url'])[0].'.com',//访问前缀
                'source_file_name'=>$file->getInfo('name'),//源文件名
                'size'=>$file->getInfo('size'),//大小(b)
                'extension'=>$extension,//扩展名
                'file_type'=>$file->getInfo('type'),//文件后缀
                'save_name'=>$filename,//保存文件名
                'new_filename'=>$new_filename,//新文件名
                'real_path'=>$res['info']['url'],//实际路径
                'outer_req_url'=>$res['info']['url'],//外部访问地址
                'outer_req_relative_url'=>$res['info']['url'],//外部访问相对地址
            ];
            return Tools::set_ok('ok', $urls);
        });
    }

    /**
     * desc：设置文件保存目录
     * author：wh
     * @param string $unique_id 唯一id，可以是用户id，可以是其它用于区分的标识
     * @return string
     */
    function setFileSaveDir($unique_id=''){
        if($unique_id){
            $unique_id = $unique_id.'/';
        }
        //项目名称
        $project_name = Tools::get_project_name();
        //控制器方法路径
        $ctl = strtolower(request()->controller().'/'.request()->action());
        return $project_name.'/'.$ctl.'/'.$unique_id.date('Ymd').'/';//日期
    }
    /**
     * desc：检测size是否在ini配置范围
     *
     * author：wh
     * @param $size
     * @return bool
     */
    private function uploadMaxFilesizeCheck($size){
        $ini_upload_max_filesize = str_replace('M','',ini_get('upload_max_filesize'));
        return $size<=$ini_upload_max_filesize;
    }


    /**
     * desc：上传base64格式图片【文件不用base64传输】
     * author：wh
     * @param string $file_upload_name
     * @param int $size
     * @param array $ext
     * @return array
     * @throws \Exception
     */
    function uploadBase64Img($file_upload_name = 'file_upload', $size=10, $ext=''){
        $source = input($file_upload_name, 'file_upload');
        $file_size = strlen($source);
        if($file_size > $size * 1024 * 1024){
            return Tools::set_res(1, '上传失败，大小限制');
        }
        if(preg_match('/^(data:\s*image\/(\w+);base64,)/', $source, $result) < 1){
            return Tools::set_res(1, '上传文件不合法');
        }
        $type = $result[2];

        if(empty($ext)) $ext = $this->file_ext;

        if(!in_array($type, explode($ext))){
            return Tools::set_res(1, '上传失败，类型限制');
        }
        $result = base64_image_content($source);
        if(false === $result){
            return Tools::set_res(1, '上传失败');
        }
        return Tools::set_res(0, '上传成功', $result);
    }

    /**
     * desc：批量上传base64格式图片【文件不用base64传输】
     * author：wh
     * @param string $file_upload_name
     * @param int $size
     * @param array $ext
     * @return array
     * @throws \Exception
     */
    function uploadBase64Imgs($file_upload_name = 'file_upload', $size=10, $ext=''){
        $source_list = input($file_upload_name, 'file_upload');
        if(!is_array($source_list)){
            return Tools::set_res(1, '参数错误');
        }

        if(empty($ext)) $ext = $this->file_ext;

        $result = [];
        $error = [];
        foreach ($source_list as $source){
            $file_size = strlen($source);
            if($file_size > $size * 1024 * 1024){
                $error[] = '上传失败，大小限制';
                continue;
            }
            if(preg_match('/^(data:\s*image\/(\w+);base64,)/', $source, $temp) < 1){
                $error[] = '上传文件不合法';
                continue;
            }
            $type = $temp[2];
            if(!in_array($type, explode(',', $ext))){
                $error[] = '类型限制';
                continue;
            }
            $up_result = base64_image_content($source);
            if(false === $up_result){
                $error[] = '上传失败';
                continue;
            }
            $result[] = $up_result;
        }

        $msg = '上传成功';
        $code = 0;
        if(count($error) > 0){
            $msg = '上传失败;提示：'.implode(',', $error);//顺带返回错误信息
            $code = 1;
        }
        return Tools::set_res($code, $msg, $result);
    }

    /**
     * desc：优化路径格式
     * author：wh
     */
    private function dealPath(string $path){
        $str = str_replace('\\','/',$path);

        return str_replace('//','/',$str);
    }


    /**
     * desc：curl上传文件，php上传文件到远程服务器地址
     *
     * [php curl模拟文件上传]
     *
     * 依赖库："guzzlehttp/guzzle": "^7.8",
     *
     * author：wh
     * @param $url
     * @param $params
     * @param false[] $config
     */
    function uploadCurlFiles($url,$params, $config=['verify' => false]){
        if(empty($this->unique_key)){
            throw new \Exception('UNIQUE_KEY 不能为空');
        }
        if(empty($this->file_lists_urls)){
            throw new \Exception('文件地址列表不能为空');
        }
        // 创建 Guzzle HTTP 客户端实例
        $client = new Client($config);

        // 定义要上传的文件列表
        $files = [
            //[
            //    'name'     => 'file1', // 服务器接收的文件字段名
            //    'contents' => Utils::tryFopen('D:\wanghua\projects\big_world_projects\universal_gravitation\public\uploads\20240506\dc1c441d81d48565ac6817b89d0f8bef.mp4', 'r'), // 文件路径
            //    'filename' => 'dc1c441d81d48565ac6817b89d0f8bef.mp4', // 文件名，可自定义
            //],
            //[
            //    'name'     => 'files',
            //    'contents' => Utils::tryFopen('D:\wanghua\projects\big_world_projects\universal_gravitation\public\uploads\20240506\f80179b23b60619fba8033bfd64f8817.mp4', 'r'),
            //    'filename' => 'f80179b23b60619fba8033bfd64f8817.mp4',
            //],
            //['name'=>'prompt','contents'=>$prompt],
            //['name'=>'tts_url','contents'=>$tts_url]
            // 可以继续添加更多文件...
        ];
        //print_r($params);
        foreach ($params as $key=>$val){
            $files[] = ['name'=>$key,'contents'=>$val];
        }
        $controller = strtolower(request()->controller());
        $action = strtolower(request()->action());
        $save_path = Tools::get_root_path() . "public/uploads/{$controller}/{$action}/".$this->unique_key;
        if(!file_exists($save_path)){
            mkdir($save_path,0777,true);
        }

        //文件远程可访问地址列表
        foreach ($this->file_lists_urls as $name=>$video_url) {
            //处理可用地址（可能存储在本地或oss）
            $video_url = $this->get_usable_url($video_url);
            $files[] = [
                'name'=>"files",//服务器接收的文件字段名
                //读取地址文件流(本地地址或远程地址均可,本地真实物理地址也行)
                'contents'=>Utils::tryFopen($video_url, 'r'),
                'filename'=>$name,//可自定义 文件名
            ];
        }

        // 构建多部分表单数据
        $multipartStream = new MultipartStream($files);
        $boundary = $multipartStream->getBoundary();
        $headers = [
            'Content-Type' => "multipart/form-data; boundary={$boundary}",
        ];

        // 准备请求体
        $body = $multipartStream->getContents();

        // 发起 POST 请求
        try {
            $postinfo = [
                'headers' => $headers,
                'body' => $body,
            ];
            //上传
            $response = $client->request('POST', $url, $postinfo);
            // 处理响应
            //$responseBody = (string) $response->getBody();
            // 检查状态码
            //if ($response->getStatusCode() !== 200) {
            //    return false;
            //}
            return $response;//返回上传结果
        } catch (\GuzzleHttp\Exception\RequestException $e) {
            // 错误处理
            //echo "Error: " . $e->getMessage();
            Tools::error_txt_log($e);
            return false;
        }
    }

    /**
     * desc：获取视频可用地址（兼容远程地址或本地地址）
     * author：wh
     * @param $video_url
     * @return string|string[]
     */
    private function get_usable_url($video_url){
        if(strpos($video_url,'http')!==false){
            return $video_url;//远程地址
        }
        return Tools::get_root_path().$video_url;//本地地址
    }



}